//
// Created by LIN on 25-8-6.
//

#include "qmediaplaylist.h"

QMediaPlaylist::QMediaPlaylist(QObject *parent) : QObject(parent)
{
}

void QMediaPlaylist::bindPlayer(QMediaPlayer *player)
{
    m_player = player;
    if (m_player && !m_playlist.isEmpty())
    {
        m_player->setSource(m_playlist.at(m_currentPos));
    }
}

// 播放模式相关
QMediaPlaylist::PlaybackMode QMediaPlaylist::playbackMode() const
{
    return m_playbackMode;
}

void QMediaPlaylist::setPlaybackMode(PlaybackMode mode)
{
    if (mode == m_playbackMode)
        return;
    m_playbackMode = mode;
    emit playbackModeChanged(mode);
}

// 当前项目相关
int QMediaPlaylist::currentIndex() const
{
    return m_currentPos;
}

QUrl QMediaPlaylist::currentMedia() const
{
    if (m_currentPos < 0 || m_currentPos >= m_playlist.size())
        return QUrl();
    return m_playlist.at(m_currentPos);
}

// 导航相关
int QMediaPlaylist::nextIndex(int steps) const
{
    return calculateNextPosition(steps);
}

int QMediaPlaylist::previousIndex(int steps) const
{
    return calculatePreviousPosition(steps);
}

int QMediaPlaylist::calculateNextPosition(int steps) const
{
    if (m_playlist.isEmpty())
        return -1;

    int next = m_currentPos + steps;

    switch (m_playbackMode)
    {
    case CurrentItemOnce:
        return steps != 0 ? -1 : m_currentPos;
    case CurrentItemInLoop:
        return m_currentPos;
    case Sequential:
        if (next >= m_playlist.size())
            next = 0;
        break;
    case Loop:
        next %= m_playlist.count();
        break;
    case Random:
        next = QRandomGenerator::global()->bounded(m_playlist.size());
        break;
    }

    return next;
}

int QMediaPlaylist::calculatePreviousPosition(int steps) const
{
    if (m_playlist.isEmpty())
        return -1;

    int next = m_currentPos;
    if (next < 0)
        next = m_playlist.size();
    next -= steps;

    switch (m_playbackMode)
    {
    case CurrentItemOnce:
        return steps != 0 ? -1 : m_currentPos;
    case CurrentItemInLoop:
        return m_currentPos;
    case Sequential:
        if (next < 0)
            next = m_playlist.size() - 1;
        break;
    case Loop:
        next %= m_playlist.size();
        if (next < 0)
            next += m_playlist.size();
        break;
    case Random:
        next = QRandomGenerator::global()->bounded(m_playlist.size());
        break;
    }

    return next;
}

// 列表操作
int QMediaPlaylist::mediaCount() const
{
    return m_playlist.count();
}

bool QMediaPlaylist::isEmpty() const
{
    return m_playlist.isEmpty();
}

QUrl QMediaPlaylist::media(int index) const
{
    if (index < 0 || index >= m_playlist.size())
        return QUrl();
    return m_playlist.at(index);
}

void QMediaPlaylist::addMedia(const QUrl &content)
{
    int pos = m_playlist.size();
    emit mediaAboutToBeInserted(pos, pos);
    m_playlist.append(content);
    emit mediaInserted(pos, pos);

    if (m_currentPos == -1 && m_player)
    {
        m_currentPos = 0;
        m_player->setSource(content);
    }
}

void QMediaPlaylist::addMedia(const QList<QUrl> &items)
{
    if (items.isEmpty())
        return;

    int first = m_playlist.size();
    int last = first + items.size() - 1;
    emit mediaAboutToBeInserted(first, last);
    m_playlist.append(items);
    emit mediaInserted(first, last);

    if (m_currentPos == -1 && m_player && !m_playlist.isEmpty())
    {
        m_currentPos = 0;
        m_player->setSource(m_playlist.first());
    }
}

bool QMediaPlaylist::insertMedia(int pos, const QUrl &content)
{
    pos = qBound(0, pos, m_playlist.size());
    emit mediaAboutToBeInserted(pos, pos);
    m_playlist.insert(pos, content);
    emit mediaInserted(pos, pos);

    if (m_currentPos >= pos)
    {
        m_currentPos++;
    }

    if (m_currentPos == -1 && m_player && !m_playlist.isEmpty())
    {
        m_currentPos = 0;
        m_player->setSource(m_playlist.first());
    }

    return true;
}

bool QMediaPlaylist::insertMedia(int pos, const QList<QUrl> &items)
{
    if (items.isEmpty())
        return true;

    pos = qBound(0, pos, m_playlist.size());
    int last = pos + items.size() - 1;
    emit mediaAboutToBeInserted(pos, last);

    auto newList = m_playlist.mid(0, pos);
    newList += items;
    newList += m_playlist.mid(pos);
    m_playlist = newList;

    emit mediaInserted(pos, last);

    if (m_currentPos >= pos)
    {
        m_currentPos += items.size();
    }

    if (m_currentPos == -1 && m_player && !m_playlist.isEmpty())
    {
        m_currentPos = 0;
        m_player->setSource(m_playlist.first());
    }

    return true;
}

bool QMediaPlaylist::removeMedia(int pos)
{
    return removeMedia(pos, pos);
}

bool QMediaPlaylist::removeMedia(int start, int end)
{
    if (end < start || end < 0 || start >= m_playlist.count())
        return false;

    start = qBound(0, start, m_playlist.size() - 1);
    end = qBound(0, end, m_playlist.size() - 1);

    emit mediaAboutToBeRemoved(start, end);
    m_playlist.remove(start, end - start + 1);
    emit mediaRemoved(start, end);

    if (m_currentPos >= start && m_currentPos <= end)
    {
        m_currentPos = -1;
        if (m_player)
            m_player->setSource(QUrl());
    }
    else if (m_currentPos > end)
    {
        m_currentPos -= (end - start + 1);
    }

    return true;
}

void QMediaPlaylist::clear()
{
    int size = m_playlist.size();
    if (size == 0)
        return;

    emit mediaAboutToBeRemoved(0, size - 1);
    m_playlist.clear();
    emit mediaRemoved(0, size - 1);

    m_currentPos = -1;
    if (m_player)
        m_player->setSource(QUrl());
}

// 播放控制
void QMediaPlaylist::next()
{
    int newPos = calculateNextPosition(1);
    if (newPos != m_currentPos && newPos != -1)
    {
        m_currentPos = newPos;
        if (m_player)
            m_player->setSource(m_playlist.at(m_currentPos));
        emit currentIndexChanged(m_currentPos);
        emit currentMediaChanged(currentMedia());
    }
}

void QMediaPlaylist::previous()
{
    int newPos = calculatePreviousPosition(1);
    if (newPos != m_currentPos && newPos != -1)
    {
        m_currentPos = newPos;
        if (m_player)
            m_player->setSource(m_playlist.at(m_currentPos));
        emit currentIndexChanged(m_currentPos);
        emit currentMediaChanged(currentMedia());
    }
}

void QMediaPlaylist::setCurrentIndex(int playlistPosition)
{
    if (playlistPosition < 0 || playlistPosition >= m_playlist.size())
        playlistPosition = -1;

    if (playlistPosition != m_currentPos)
    {
        m_currentPos = playlistPosition;
        if (m_player && m_currentPos != -1)
        {
            m_player->setSource(m_playlist.at(m_currentPos));
        }
        emit currentIndexChanged(m_currentPos);
        emit currentMediaChanged(currentMedia());
    }
}

void QMediaPlaylist::shuffle()
{
    if (m_playlist.size() <= 1)
        return;

    QList<QUrl> shuffled;
    QList<QUrl> remaining = m_playlist;

    // 保留当前播放项的位置
    if (m_currentPos != -1)
    {
        shuffled.append(remaining.takeAt(m_currentPos));
    }

    while (!remaining.isEmpty())
    {
        shuffled.append(remaining.takeAt(QRandomGenerator::global()->bounded(remaining.size())));
    }

    m_playlist = shuffled;
    emit mediaChanged(0, m_playlist.count() - 1);
}